﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PeoplesJukebox.Core.Interfaces;
using PeoplesJukebox.Core.MediaItems;
using System.Threading;
using PeoplesJukebox.Core.Logging;
using config = PeoplesJukebox.Core.Configuration;
using System.Reflection;
using FMODNet;

namespace PeoplesJukebox.Core.Players
{
    /// <summary>
    /// Media player implementation using the FMOD library
    /// </summary>
    /// <seealso cref="TODO"/>
    public class FMODPlayer : IMediaPlayer
    {
        #region Private static fields

        private static Track _currentTrack;
        private static Sound _currentSound;
        private static int _mediaErrorCount;
        private static SoundDevice _player;

        #endregion

        #region Constructors

        /// <summary>
        /// Static constructor
        /// </summary>
        static FMODPlayer()
        {
            _mediaErrorCount = 0;
            _player = new SoundDevice();
            _player.Initialize();
        }

        #endregion

        #region IMediaPlayer implementation

        /// <summary>
        /// Gets the currently-playing track
        /// </summary>
        public Track CurrentTrack
        {
            get { return _currentTrack; }
        }

        /// <summary>
        /// Starts playback
        /// </summary>
        public void Start()
        {
            PlayNext();
        }        

        /// <summary>
        /// Skips playback to the next track
        /// </summary>
        public void Skip()
        {
            PlayNext();
        }

        /// <summary>
        /// Stops playback
        /// </summary>
        public void Stop()
        {
            StopInternal();
        }

        #endregion

        #region Private static methods

        private static void PlayNext()
        {
            Track nextTrack = PeoplesJukeboxService.GetNextTrack();
            if (nextTrack != null)
            {
                try
                {
                    StopInternal();
                    PlayCallback(nextTrack);
                }
                catch (Exception ex)
                {
                    Log.Error("FMODPlayer.PlayNext errored: {0}", ex.Message);
                }
                _currentTrack = nextTrack;
            }
        }

        private static void PlayCallback(Track nextTrack)
        {
            _currentSound = _player.CreateSound(nextTrack.Uri);
            Log.Info("FMODPlayer.PlayCallback, new URL={0}", nextTrack.Uri);
            _currentSound.Play();
            Log.Info("FMODPlayer.PlayCallback, called Play()");
            _currentSound.AddCallback((uint)(_currentSound.Length - 2000), (c, x) => PlayNext());
            //TODO - add fader?
            Log.Info("FMODPlayer.PlayCallback, added callbacks");
        }

        static void StopInternal()
        {
            if (_currentSound != null)
            {
                _currentSound.Stop();
            }
        }

        #endregion

        #region Extension option - fade in/out

        //void PlayNextSound()
        //{
        //    sndPos = (sndPos % listBox1.Items.Count);
        //    Sound snd = _currentSound;

        //    sndPos = chkRandom.Checked ? rnd.Next(listBox1.Items.Count) : sndPos++;

        //    EventHandler hwnd = (c, x) => { selectListBox(); };
        //    hwnd.SmartInvoke(listBox1);

        //    SoundInfo filename = listBox1.Items[sndPos] as SoundInfo;

        //    Sound sound = device.CreateSound(filename.Filename);
        //    _currentSound = sound;

        //    sound.Name = Path.GetFileNameWithoutExtension(filename.Filename);

        //    Fader fader = sound.AddDSP(new Fader(sound.Length - 6000, sound.Length, this.device));
        //    fader.Bypass = false;

        //    sound.Play();
        //    sound.AddCallback((uint)(10000), (c, x) => { });
        //    sound.AddCallback((uint)(sound.Length - 2000), (c, x) => PlayNextSound());
        //    sound.AddCallback((uint)(sound.Length - 6000), (c, x) => StartFeedFade(c));
        //    SetTitle(sound);
        //}

        #endregion
    }
}
